package threadUtils.demo02;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

public class CyclicBarrierExample03 {

    public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
        // 11人
        CyclicBarrier barrier = new CyclicBarrier(11);
        for (int i = 0; i < 10; i++) {
            new Thread(new Tourist(i, barrier)).start();
        }
        // 主线程阻塞，等待所有人上车中
        int await = barrier.await();
        System.out.println("All people get on the bus，await：" + await);

        // 主线程阻塞，等待所有人下车中
        barrier.await();
        System.out.println("All people get off the bus");
    }

}

class Tourist implements Runnable {

    private final int personId;
    private final CyclicBarrier barrier;

    public Tourist(int personId, CyclicBarrier barrier) {
        this.personId = personId;
        this.barrier = barrier;
    }

    @Override
    public void run() {
        System.out.printf("People: %d by bus \n", personId);
        // 上车
        seconds();
        barrier("Person: %d Get on bus, and wait other people \n");

        System.out.printf("People: %d 行程中 \n", personId);
        // 下车
        seconds();
        // 清点人数
        barrier("People: %d Get off the bus, and wait the other people \n");
    }

    private void seconds() {
        try {
            TimeUnit.MILLISECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void barrier(String message) {
        System.out.printf(message, personId);
        try {
            barrier.await();
//            System.out.println("barrier await：" + await);
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}
